class Snake {
    //表示蛇头的元素
    head: HTMLElement;
    //蛇的身体(包括蛇头)
    bodies: HTMLCollection
    //获取蛇的容器
    element: HTMLElement

    constructor() {
        this.head = document.querySelector('#snake>div') as HTMLElement;
        this.element = document.getElementById('snake')!;
        this.bodies = this.element.getElementsByTagName('div');
    }
    //获取蛇的坐标(蛇头坐标)
    get X() {
        return this.head.offsetLeft;
    }
    get Y() {
        return this.head.offsetTop;
    }
    //设置蛇的坐标
    set X(value) {
        //如果新值和旧值相同，则直接返回不再修改
        if (this.X === value) {
            return;
        }
        //X的值合法范围
        if (value < 0 || value > 290) {
            //进入判断说明蛇撞墙了
            throw new Error('蛇撞墙了')
        }

        //修改X时，是在修改水平坐标，蛇在向左移动时，不能向右掉头，反之亦然
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
            //水平方向发生了掉头
            if (value > this.X) {
                value = this.X - 10;
            } else {
                value = this.X + 10;
            }
        }

        //移动身体
        this.moveBody()

        this.head.style.left = value + 'px'

        this.checkHeadBody();
    }
    set Y(value) {
        if (this.Y === value) {
            return;
        }
        //Y的值合法范围
        if (value < 0 || value > 290) {
            //进入判断说明蛇撞墙了
            throw new Error('蛇撞墙了')
        }

        //修改Y时，是在修改垂直坐标，蛇在向上移动时，不能向下掉头，反之亦然
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
            //水平方向发生了掉头
            if (value > this.Y) {
                value = this.Y - 10;
            } else {
                value = this.Y + 10;
            }
        }

        //移动身体
        this.moveBody()

        this.head.style.top = value + 'px'

        this.checkHeadBody();
    }

    //蛇增加身体的方法
    addBody() {
        //向element中添加一个div
        this.element.insertAdjacentHTML('beforeend', "<div></div>")
    }

    //添加一个蛇身体移动的方法
    moveBody() {
        //将后边的身体设置到前面一节身体的位置
        /**
         * 第4节 == 第3节的位置
         * 第3节 == 第3节的位置
         * 第2节 == 头的位置
         **/
        for (let i = this.bodies.length - 1; i > 0; i--) {
            //获取前边一节身体的位置
            let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
            let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

            //将X和Y设置到当前身体
            (this.bodies[i] as HTMLElement).style.left = X + 'px';
            (this.bodies[i] as HTMLElement).style.top = Y + 'px';

        }
    }

    //检查蛇头是否和身体相撞
    checkHeadBody() {
        //获取所有的身体，检查其是否和蛇头的坐标发生重叠
        for (let i = 1; i < this.bodies.length; i++) {
            let bd = this.bodies[i] as HTMLElement
            if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
                //进入判断 说明撞到身体，游戏结束
                throw new Error('撞到我自己了！')
            }
        }
    }
}

export default Snake;